package cs4383;

/* Reference:
 * An Java3D NyARToolkit example
 * MultiNyAR.java
 * Andrew Davison, ad@fivedots.coe.psu.ac.th, April 2010
 */

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.SystemColor;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import javax.media.j3d.AmbientLight;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Locale;
import javax.media.j3d.PhysicalBody;
import javax.media.j3d.PhysicalEnvironment;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.media.j3d.ViewPlatform;
import javax.media.j3d.VirtualUniverse;
//import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import javax.vecmath.Color3f;
import javax.vecmath.Point2d;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import jp.nyatla.nyartoolkit.NyARException;
import jp.nyatla.nyartoolkit.java3d.utils.J3dNyARParam;

import org.apache.log4j.Logger;
import org.jdesktop.swingx.JXTitledPanel;

import ar.DetectMarkers;
import ar.NyARMarkersBehavior;

import com.sun.j3d.utils.universe.SimpleUniverse;
import com.swtdesigner.FocusTraversalOnArray;
import java.awt.Color;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;

public class ProjectGUI extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = -1512624058057563147L;

	Logger logger = Logger.getLogger(this.getClass());

	private final String PARAMS_FNM = "camera_para.dat";

	private static final int PWIDTH = 640; // size of panel
	private static final int PHEIGHT = 480;

	// private static final double SHAPE_SIZE = 0.02;

	private static final int BOUNDSIZE = 100; // larger than world

	private J3dNyARParam cameraParams;

	private List<Furniture> furnitures = new ArrayList<Furniture>();
	private String[] chairs = { "05", "049", "089", "102", "107", "108", "115" };
	private String[] tables = { "045", "066" };
	private List<Furniture> chairModel = new ArrayList<Furniture>();
	private List<Furniture> tableModel = new ArrayList<Furniture>();

	private CustomMarkerModel mm1;
	private CustomMarkerModel mm2;
	private CustomMarkerModel selected;

	private static Canvas3D canvas;
	// private DefaultListModel model = new DefaultListModel();
	private JList listMarkers;
	private JList listFurniture;
	private JTextPane txtpnTestFruniture;
	// private BufferedImage[] images = new BufferedImage[chairs.length];
	private JScrollPane scrollPaneFurniture;
	private Vector<JPanel> furnitureVector = new Vector<JPanel>();
	private Vector<JPanel> markerVector = new Vector<JPanel>();
	double angle = 0.0;
	double scale = 1.0;
	int fIdx = 0;
	private Canvas3D c3d_1;
	private JXTitledPanel markerPanel;
	private JXTitledPanel detailPanel;
	private JXTitledPanel controlPanel;

	public ProjectGUI() {
		// super("Multiple markers NyARToolkit Example");
		super("AR Interior designer");

		cameraParams = readCameraParams(PARAMS_FNM);
		JPopupMenu.setDefaultLightWeightPopupEnabled(false);
		furnitures = loadChairs();
		loadTables();
		loadImages(chairs);

		Container cp = getContentPane();

		// create a JPanel in the center of JFrame
		JPanel p = new JPanel();
		p.setBackground(SystemColor.control);
		p.setPreferredSize(new Dimension(PWIDTH, PHEIGHT));
		cp.add(p, BorderLayout.WEST);
		p.setLayout(null);

		// put the 3D canvas inside the JPanel
		canvas = createCanvas3D();
		// p.add(canvas);
		JLayeredPane layeredPane = new JLayeredPane();
		// /JXPanel layeredPane = new JXPanel();

		layeredPane.setBounds(0, 21, 640, 359);
		p.add(layeredPane);

		JMenuBar menuBar = new JMenuBar();
		menuBar.setBounds(0, 0, 640, 21);
		// p.add(menuBar);
		p.add(menuBar);

		// TODO remove/disable unused group
		JMenu mnFurnitureFilter = new JMenu("Furniture Filter");
		menuBar.add(mnFurnitureFilter);

		JMenu mnByFunction = new JMenu("By Function");
		mnFurnitureFilter.add(mnByFunction);

		JMenu mntmAppliances = new JMenu("Appliances");
		mnByFunction.add(mntmAppliances);

		JMenu mnComfort = new JMenu("Comfort");
		mnByFunction.add(mnComfort);

		JMenuItem mntmAll = new JMenuItem("All");
		mnComfort.add(mntmAll);

		JMenuItem mntmBedsAndBedding = new JMenuItem("Beds and Bedding");
		mnComfort.add(mntmBedsAndBedding);

		JMenuItem mntmDiningAndOther = new JMenuItem("Dining and Other Chairs");
		mnComfort.add(mntmDiningAndOther);

		JMenuItem mntmLivingChairs = new JMenuItem(
				"Living Chairs and Recliners");
		mnComfort.add(mntmLivingChairs);

		JMenuItem mntmSofasAndLoveseats = new JMenuItem("Sofas and Loveseats");
		mnComfort.add(mntmSofasAndLoveseats);

		JMenu mnDecorative = new JMenu("Decorative");
		mnByFunction.add(mnDecorative);

		JMenu mnElectronics = new JMenu("Electronics");
		mnByFunction.add(mnElectronics);

		JMenu mnLighting = new JMenu("Lighting");
		mnByFunction.add(mnLighting);

		JMenu mnMiscellaneous = new JMenu("Miscellaneous");
		mnByFunction.add(mnMiscellaneous);

		JMenu mnPlumbing = new JMenu("Plumbing");
		mnByFunction.add(mnPlumbing);

		JMenu mnSurfaces = new JMenu("Surfaces");
		mnByFunction.add(mnSurfaces);

		JMenu mnByRoom = new JMenu("By Room");
		mnFurnitureFilter.add(mnByRoom);

		JMenu mnBathroom = new JMenu("Bathroom");
		mnByRoom.add(mnBathroom);

		JMenu mnBedroom = new JMenu("Bedroom");
		mnByRoom.add(mnBedroom);

		JMenu mnDining = new JMenu("Dining");
		mnByRoom.add(mnDining);

		JMenu mnKitchen = new JMenu("Kitchen");
		mnByRoom.add(mnKitchen);

		JMenu mnLivingRoom = new JMenu("Living");
		mnByRoom.add(mnLivingRoom);

		JMenuItem mntmChair = new JMenuItem("Chair");

		mntmChair.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// System.out.println("click");
				// loadChairs();
				furnitures = new ArrayList<Furniture>();
				furnitures = chairModel;
				loadImages(chairs);
				loadFurnitureToList();
			}
		});
		mnLivingRoom.add(mntmChair);

		JMenuItem mntmTable = new JMenuItem("Table");
		mntmTable.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// loadTables();
				furnitures = tableModel;
				loadImages(tables);
				loadFurnitureToList();

			}
		});
		mnLivingRoom.add(mntmTable);

		JMenu mntmCamera = new JMenu("Camera");
		menuBar.add(mntmCamera);

		JMenu mntmOption = new JMenu("Options");
		menuBar.add(mntmOption);

		// JMenuItem optShowHide = new JMenuItem("Show/Hide left panel");
		// optShowHide.addActionListener(new ActionListener() {
		// public void actionPerformed(ActionEvent e) {
		// if (listMarkers.isVisible()) {
		// listMarkers.setVisible(false);
		// txtpnTestFruniture.setVisible(false);
		// } else {
		// listMarkers.setVisible(true);
		// txtpnTestFruniture.setVisible(true);
		// }
		//
		// }
		// });
		// mntmOption.add(optShowHide);

		JMenu mntmHelp = new JMenu("Help");
		menuBar.add(mntmHelp);

		JMenuItem mntmShowHelpMessage = new JMenuItem("Show Help Message");
		mntmHelp.add(mntmShowHelpMessage);
		mntmShowHelpMessage.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO help function
				// help message string

				String helpMsg = "The following operation is supported\n"
						+ "A - Rotate Left\n" + "D - Rotate Right\n"
						+ "W - Enlarge model\n" + "S - Shrink model\n"
						+ "R - Reset model\n" + "K - Select next model\n";
				// non-modal window, blocked main window

				JOptionPane.showMessageDialog(null, helpMsg, "Help Message",
						JOptionPane.INFORMATION_MESSAGE);
			}

		});

		markerPanel = new JXTitledPanel("Markers");
		markerPanel.setBounds(0, 0, 161, 76);
		layeredPane.add(markerPanel);

		// listMarkers = new JList(model);
		listMarkers = new JList();
		listMarkers.setVisibleRowCount(1);
		listMarkers.setLayoutOrientation(JList.HORIZONTAL_WRAP);
		listMarkers.setToolTipText("markers");
		listMarkers.setBounds(0, 0, 147, 88);
		listMarkers.setCellRenderer(new ImageRenderer());
		// layeredPane.add(listMarkers);
		markerPanel.add(listMarkers);
		listMarkers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		if (listMarkers.getModel().getSize() > 0) {
			listMarkers.setSelectedIndex(0);
		}
		markerVector.addElement(loadMarkerImage("Data/pattHiro.png"));
		markerVector.addElement(loadMarkerImage("Data/pattKanji.png"));
		loadFurnitureToMarker();
		listMarkers.addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent e) {
				// String value = (String) listMarkers.getSelectedValue();
				// String ss[] = value.split("\\");
				// String marker = ss[0];
				// if (marker.equals("hiro"))
				// selected = mm1;
				// else
				// selected = mm2;
				if (!txtpnTestFruniture.isVisible()) {
					txtpnTestFruniture.setVisible(true);
				}
				logger.debug(listMarkers.getSelectedIndex());
				if (listMarkers.getSelectedIndex() == 0) {
					selected = mm1;
				} else {
					selected = mm2;
				}
				updateDetailPanelTxt(selected.getFurniture());
				listFurniture.clearSelection();
			}
		});

		txtpnTestFruniture = new JTextPane();
		txtpnTestFruniture.setText("Details:");
		txtpnTestFruniture.setEditable(false);
		txtpnTestFruniture.setBounds(0, 175, 161, 184);
		detailPanel = new JXTitledPanel("Details");
		detailPanel.setBounds(0, 183, 161, 176);
		layeredPane.add(detailPanel);
		detailPanel.add(txtpnTestFruniture);
		txtpnTestFruniture.setVisible(true);
		scrollPaneFurniture = new JScrollPane();
		scrollPaneFurniture.setBounds(0, 380, 640, 100);
		p.add(scrollPaneFurniture);

		// listFurniture = new JList();
		listFurniture = new JList();
		scrollPaneFurniture.setViewportView(listFurniture);
		listFurniture.setCellRenderer(new ImageRenderer());
		listFurniture.setVisibleRowCount(1);
		listFurniture.setLayoutOrientation(JList.HORIZONTAL_WRAP);
		// listFurniture.setCellRenderer(new ImageRenderer());
		listFurniture.addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent arg0) {
				int i = listFurniture.getSelectedIndex();
				System.out.println(i);
				// System.out.println(listFurniture.getSelectedValue());
				if (selected != null && i >= 0) {
					selected.setFurniture(furnitures.get(i));
					System.out.println(selected.getNameInfo());
					updateDetailPanelTxt(furnitures.get(i));
					// int index = listMarkers.getSelectedIndex();
					// if (index >= 0) {
					// String names[] = furnitures.get(i).getName().split(" ");
					// JPanel markPanel = loadMarkerImage(names[1]);
					// markerVector.set(index, markPanel);
					// loadFurnitureToMarker();
					// }
				} else {
					System.out.println("No marker is selected");
				}
				// scrollPaneFurniture.setVisible(false);
			}

		});
		listFurniture.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

		listFurniture.setListData(furnitureVector);
		// JPanel jp1 = new JPanel();
		// jp1.add(new JLabel(new ImageIcon("models/" + chairs[0] + ".jpg")));
		// jp1.add(new JLabel(chairs[0]));
		// jp1.setBounds(0, 50, 80,100 );
		// p.add(jp1);
		// TODO
		// panelFurniture.setVisible(false);
		// p.add(canvas);
		layeredPane.add(canvas);
		controlPanel = new JXTitledPanel("Control");
		controlPanel.setBounds(0, 76, 161, 107);

		layeredPane.add(controlPanel);
		controlPanel.getContentContainer().setLayout(null);
		JToolBar toolBarRotate = new JToolBar();
		toolBarRotate.setBackground(Color.WHITE);
		toolBarRotate.setBounds(0, 0, 159, 39);
		controlPanel.getContentContainer().add(toolBarRotate);
		toolBarRotate.setFloatable(false);
		toolBarRotate.setRollover(true);

		JButton btnAntiClockwise = new JButton(new ImageIcon("pic/left.png"));
		btnAntiClockwise.setToolTipText("Anti-clockwise");
		btnAntiClockwise.setBackground(Color.WHITE);
		btnAntiClockwise.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (selected != null) {
					// angle += 0.1;
					selected.rotateAntiClockwise(0.1);
				}
			}
		});

		JButton btnRefresh = new JButton(new ImageIcon("pic/refresh.png"));
		btnRefresh.setToolTipText("Original position");
		btnRefresh.setBackground(Color.WHITE);
		btnRefresh.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (selected != null) {
					angle = 0;
					selected.rotateZ(angle);
				}
			}
		});
		toolBarRotate.add(btnRefresh);
		toolBarRotate.add(btnAntiClockwise);

		JButton btnClockWise = new JButton(new ImageIcon("pic/right.png"));
		btnClockWise.setBackground(Color.WHITE);
		btnClockWise.setToolTipText("Clockwise");
		btnClockWise.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (selected != null) {
					// angle -= 0.1;
					// selected.rotateZ(angle);
					selected.rotateClockwise(0.1);
				}
			}
		});
		toolBarRotate.add(btnClockWise);

		JToolBar toolBarSize = new JToolBar();
		toolBarSize.setBackground(Color.WHITE);
		toolBarSize.setBounds(0, 39, 159, 39);
		controlPanel.getContentContainer().add(toolBarSize);
		toolBarSize.setRollover(true);
		toolBarSize.setFloatable(false);

		JButton btnIn = new JButton(new ImageIcon("pic/in.png"));
		btnIn.setToolTipText("Enlarge");
		btnIn.setBackground(Color.WHITE);
		btnIn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (selected != null) {
					// scale += 0.1;
					Furniture f = selected.getFurniture();
					f.setScale((float) 0.1);
					selected.setFurniture(f);
					selected.scaleUp(0.1);
					updateDetailPanelTxt(selected.getFurniture());

				}
			}
		});

		JButton btnFit = new JButton(new ImageIcon("pic/fit.png"));
		btnFit.setToolTipText("Original size");
		btnFit.setBackground(Color.WHITE);
		btnFit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (selected != null) {
					scale = 1;
					Furniture f = selected.getFurniture();
					f.setScale((float) scale);
					selected.setFurniture(f);
					selected.setScale(scale);
					updateDetailPanelTxt(selected.getFurniture());

				}
			}
		});
		toolBarSize.add(btnFit);
		toolBarSize.add(btnIn);

		JButton btnOut = new JButton(new ImageIcon("pic/out.png"));
		btnOut.setBackground(Color.WHITE);
		btnOut.setToolTipText("Shrink");
		btnOut.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (selected != null) {
					// scale -= 0.1;
					if (selected.getScale() - 0.1 <= 0.1) {
						JOptionPane
								.showMessageDialog(
										null,
										"Furniture cannot be shrunk due to size limitation.",
										"Size limit reached",
										JOptionPane.ERROR_MESSAGE);
					} else {

						Furniture f = selected.getFurniture();
						f.setScale((float) -0.1);
						selected.setFurniture(f);
						selected.scaleDown(0.1);
						updateDetailPanelTxt(selected.getFurniture());
					}
				}
			}
		});
		toolBarSize.add(btnOut);

		final JSpinner spinner = new JSpinner();
		spinner.setModel(new SpinnerNumberModel(0.0, null, null, 0.1));
		spinner.setForeground(Color.WHITE);
		spinner.setBackground(Color.WHITE);
		spinner.setToolTipText("fine turn the rotation");
		spinner.setValue(0.1);
		spinner.addChangeListener(new ChangeListener() {
			
			@Override
			public void stateChanged(ChangeEvent e) {
				if (selected != null) {
					// angle -= 0.1;
					// selected.rotateZ(angle);
					float v=Float.parseFloat(spinner.getValue().toString());
					selected.rotateClockwise(v);
				}
				
			}
		});

		toolBarRotate.add(spinner);

		// JSpinner spinner2 = new JSpinner();
		// spinner2.setModel(new SpinnerNumberModel(1.0, null, null, 0.1));
		// //spinner2.set
		// spinner2.setForeground(Color.WHITE);
		// spinner2.setBackground(Color.WHITE);
		// spinner2.setToolTipText("fine turn the rotation");
		// spinner2.setValue(0.1);
		// //spinner.ad
		// toolBarSize.add(spinner2);

		final JSpinner spinner_1 = new JSpinner();
		spinner_1.setBounds(0, 0, 10, 15);
		spinner_1.setModel(new SpinnerNumberModel(1.0, null, null, 0.01));
		spinner_1.setForeground(Color.WHITE);
		spinner_1.setEditor(new JSpinner.NumberEditor(spinner_1, "0%"));
		spinner_1.setToolTipText("fine turn the size");
		spinner_1.addChangeListener(new ChangeListener() {

			//float value = (float) 1.0;

			@Override
			public void stateChanged(ChangeEvent e) {
				// TODO Auto-generated method stub
				if (selected != null) {
					// scale += 0.1;
					Furniture f = selected.getFurniture();
					float value = (float) selected.getScale();
					float v = Float.parseFloat(spinner_1.getValue().toString()) / 100;
					if (value < v) {
						logger.debug("scale up: " + v);
						selected.scaleUp(v);
					} else {
						logger.debug("scale down" + v);
						selected.scaleDown(v);
					}
					//selected.setScale(v);
					value = v;
					f.setScale(v);
					selected.setFurniture(f);

					updateDetailPanelTxt(selected.getFurniture());

				}
			}
		});
		toolBarSize.add(spinner_1);

		// layeredPane.setFocusTraversalPolicy(new FocusTraversalOnArray(
		// new Component[] { c3d_1, listMarkers, toolBarRotate,
		// btnRefresh, btnAntiClockwise, btnClockWise, btnFit,
		// btnIn, btnOut }));
		p.setFocusTraversalPolicy(new FocusTraversalOnArray(new Component[] {
				layeredPane, listMarkers, toolBarRotate, c3d_1, btnRefresh,
				btnAntiClockwise, btnClockWise, btnFit, btnIn, btnOut, menuBar,
				mntmAll, mntmBedsAndBedding, mntmDiningAndOther,
				mntmLivingChairs, mntmSofasAndLoveseats, mnDecorative,
				mnElectronics, mnLighting, mnMiscellaneous, mnPlumbing,
				mnSurfaces, mnByRoom, mnBathroom, mnBedroom, mnDining,
				mnKitchen, mnLivingRoom, mntmChair, mntmTable, mntmCamera,
				mntmOption, mntmHelp, scrollPaneFurniture, listFurniture }));

		KeyboardFocusManager.getCurrentKeyboardFocusManager()
				.addKeyEventDispatcher(new KeyEventDispatcher() {

					@Override
					public boolean dispatchKeyEvent(KeyEvent ke) {
						System.out.println(ke.getKeyChar());
						return false;
					}

				});
		canvas.addKeyListener(new KeyListener() {
			double angle = 0.0;
			double scale = 1.0;
			// double px = 0.0;
			// double py = 0.0;

			int fIdx = 0;

			@Override
			public void keyTyped(KeyEvent ke) {
				CustomMarkerModel cmm = ProjectGUI.this.getSelectedMarker();
				if (cmm != null) {
					switch (ke.getKeyChar()) {
					case 'r':
						scale = 1;
						cmm.setScale(scale);
						break;
					case 'a':
						angle += 0.1;
						cmm.rotateZ(angle);
						break;
					case 'd':
						angle -= 0.1;
						cmm.rotateZ(angle);
						break;
					case 'w':
						scale += 0.1;
						cmm.setScale(scale);
						break;
					case 's':
						scale -= 0.1;
						cmm.setScale(scale);
						break;
					case 'k':
						int idx = fIdx++ % (furnitures.size() - 1);
						Furniture f = furnitures.get(idx);
						logger.debug("Furniture: " + f.getName());
						cmm.setFurniture(f);
						updateDetailPanelTxt(f);
						// TODO change the image/object selected at the bottom
						// TODO debug
						// TODO bug with diff marker
						listFurniture.setSelectedIndex(idx);
						listFurniture.ensureIndexIsVisible(idx);

						break;
					}
				}
			}

			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
			}
		});

		// set default model
		mm1.setFurniture(furnitures.get(0));
		mm2.setFurniture(furnitures.get(1));

		// configure the JFrame
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		pack();
		this.setLocationRelativeTo(null);
		setVisible(true);

		selected = mm1;
		listMarkers.setSelectedIndex(0);
		updateDetailPanelTxt(selected.getFurniture());
	} // end of MultiNyAR()

	public CustomMarkerModel getSelectedMarker() {
		if (selected == null)
			return mm2;
		return selected;
	}

	public void setSelectedMarker(CustomMarkerModel selected) {
		this.selected = selected;
	}

	public List<Furniture> loadTables() {
		// furnitures = new ArrayList<Furniture>();
		Furniture f;
		for (int i = 0; i < tables.length; i++) {
			f = new Furniture(tables[i] + ".obj", 0.3, false);
			f.setName("Table " + tables[i]);
			f.setCategory("Living - Tables");
			f.setPrice(Integer.parseInt(tables[i]) + 300
					+ Integer.parseInt(tables[i]) * 4);
			if ((i + 1) % 3 == 1) {
				f.setDesigner("Anthony Lau");
			} else if ((i + 1) % 3 == 2) {
				f.setDesigner("Edman Hung");
			} else if ((i + 1) % 3 == 3) {
				f.setDesigner("Kelvin Yip");
			} else {// no way
				f.setDesigner("Anthony");
			}
			f.setImageIcon(new ImageIcon("models/" + tables[i] + ".jpg"));
			tableModel.add(f);
		}
		return tableModel;
	}

	public List<Furniture> loadChairs() {
		// furnitures = new ArrayList<Furniture>();
		Furniture f;
		for (int i = 0; i < chairs.length; i++) {
			f = new Furniture(chairs[i] + ".obj", 0.3, true);
			f.setName("Chair " + chairs[i]);
			f.setCategory("Living - Chairs");
			f.setPrice(Integer.parseInt(chairs[i]) + 100
					+ Integer.parseInt(chairs[i]) * 3);
			if ((i + 1) % 3 == 1) {
				f.setDesigner("Anthony Lau");
			} else if ((i + 1) % 3 == 2) {
				f.setDesigner("Edman Hung");
			} else if ((i + 1) % 3 == 3) {
				f.setDesigner("Kelvin Yip");
			} else {// no way
				f.setDesigner("Anthony");
			}
			int num = Integer.parseInt(chairs[i]);
			f.setWidth(num);
			f.setHeight(Math.round(num * 1.2));
			ImageIcon icon = new ImageIcon("models/" + chairs[i] + ".jpg");
			Image img = icon.getImage();
			Image resizedImage = img.getScaledInstance(45, 45,
					java.awt.Image.SCALE_SMOOTH);

			f.setImageIcon(new ImageIcon(resizedImage));
			// f.setImageIcon(new ImageIcon());
			chairModel.add(f);
		}
		return chairModel;
	}

	private void updateDetailPanelTxt(Furniture f) {
		logger.debug("updateDetailPanelTxt() - " + f);
		if (f != null) {
			// String temp = "Details:\n";
			String temp = "\n";
			// temp += "Product name - \n" + f.getName() + "\n";
			temp += f.getName() + "\n";
			if (f.getDesigner() != null && !f.getDesigner().equals(""))
				temp += "Designer: " + f.getDesigner() + "\n";

			if (f.getCategory() != null && !f.getCategory().equals(""))
				temp += "Category: " + f.getCategory() + "\n";

			if (f.getPrice() > 0)
				temp += "HKD$" + f.getPrice() + "\n";

			if (f.getDescription() != null && !f.getDescription().equals(""))
				temp += "\nDescription: \n" + f.getDescription() + "\n";
			if (f.getWidth() > 0)
				temp += "Width:" + f.getWidth() + " (cm)\n";
			if (f.getHeight() > 0)
				temp += "Height:" + f.getHeight() + " (cm)\n";
			if (f.getFeatures() != null && !f.getFeatures().equals(""))
				temp += "\nFeatures: \n" + f.getFeatures() + "\n";
			// if (f.getFeatures() != null && !f.getFeatures().equals(""))
			// temp += "\nFeatures: \n" + f.getFeatures() + "\n";

			txtpnTestFruniture.setText(null);
			txtpnTestFruniture.setText(temp);

			StyledDocument doc = (StyledDocument) txtpnTestFruniture
					.getDocument();

			// The image must first be wrapped in a style
			Style style = doc.addStyle("image_icon", null);
			StyleConstants.setIcon(style, f.getImageIcon());
			// Insert the image at the end of the text
			try {
				doc.insertString(0, "ignored text", style);
			} catch (BadLocationException e) {
				e.printStackTrace();
			}
		}

	}

	// private void setExistedMarker() {
	// if (mm1 != null) {
	// if (!model.contains(mm1.getNameInfo()))
	// model.addElement(mm1.getNameInfo());
	// } else {
	// if (model.contains(mm1.getNameInfo())) {
	// model.removeElement(mm1.getNameInfo());
	// }
	// }
	// if (mm2 != null) {
	// if (!model.contains(mm2.getNameInfo()))
	// model.addElement(mm2.getNameInfo());
	// } else {
	// if (model.contains(mm2.getNameInfo())) {
	// model.removeElement(mm2.getNameInfo());
	// }
	// }
	// }

	private void loadFurnitureToList() {
		// scrollPaneFurniture.setVisible(true);
		// System.out.println("chairs");
		// listFurniture.removeAll();
		listFurniture.setListData(furnitureVector);
		this.repaint();
	}

	private void loadFurnitureToMarker() {

		listMarkers.setListData(markerVector);

	}

	private void loadImages(String[] furniture) {
		furnitureVector = new Vector<JPanel>();
		for (int i = 0; i < furniture.length; i++) {
			// File path = new File("models/" + chairs[i] + ".jpg");
			// images[i] = ImageIO.read(path);
			JPanel jp1 = new JPanel();
			jp1.add(new JLabel(new ImageIcon("models/" + furniture[i] + ".jpg")));
			jp1.add(new JLabel(furniture[i]));
			// jp1.add(new JLabel(new ImageIcon("gumby2.gif")));
			furnitureVector.addElement(jp1);
		}
	}

	private JPanel loadMarkerImage(String imageName) {
		JPanel p = new JPanel();
		// String i = "models/" + imageName + ".jpg";
		String i = imageName;
		ImageIcon icon = new ImageIcon(i);
		Image img = icon.getImage();
		Image resizedImage = img.getScaledInstance(40, 40,
				java.awt.Image.SCALE_SMOOTH);
		p.add(new JLabel(new ImageIcon(resizedImage)));

		return p;

	}

	private J3dNyARParam readCameraParams(String fnm) {
		J3dNyARParam cameraParams = null;
		try {
			cameraParams = new J3dNyARParam();
			cameraParams.loadARParamFromFile(fnm);
			cameraParams.changeScreenSize(PWIDTH, PHEIGHT);
		} catch (NyARException e) {
			System.out.println("Could not read camera parameters from " + fnm);
			System.exit(1);
		}
		return cameraParams;
	} // end of readCameraParams()

	private Canvas3D createCanvas3D()
	/*
	 * Build a 3D canvas for a Universe which contains the 3D scene and view
	 * univ --> locale --> scene BG | ---> view BG --> Canvas3D (set up using
	 * camera cameraParams)
	 */
	{
		Locale locale = new Locale(new VirtualUniverse());
		locale.addBranchGraph(createSceneGraph()); // add the scene

		// get the preferred graphics configuration for the default screen
		GraphicsConfiguration config = SimpleUniverse
				.getPreferredConfiguration();
		c3d_1 = new Canvas3D(config);
		// Canvas3D c3d = new Canvas3D(config) {
		// @Override
		// public void postRender() {
		// // TODO
		// if (mm1.getPos() != null) {
		// Point2d p2d = ProjectGUI.getPoint2DFromCanvas3D(canvas,
		// mm1.getPos());
		// // System.out.println(p2d);
		// Rectangle2D.Double cubeBoundsOnScreen = new Rectangle2D.Double(
		// p2d.x - 50, p2d.y - 50, 100, 100);
		//
		// J3DGraphics2D g2D = getGraphics2D();
		// g2D.setPaint(Color.RED);
		// g2D.setStroke(new BasicStroke(2.0f));
		// g2D.draw(cubeBoundsOnScreen);
		// g2D.drawString("Test", (float)p2d.x, (float)p2d.y);
		// g2D.flush(false);
		// }
		// }
		// };
		c3d_1.setBounds(161, 0, 479, 359);
		locale.addBranchGraph(createView(c3d_1)); // add view branch

		return c3d_1;
	} // end of createCanvas3D()

	public static Point2d getPoint2DFromCanvas3D(Canvas3D c, Point3d p3d) {
		Transform3D temp = new Transform3D();
		c.getVworldToImagePlate(temp);
		temp.invert();
		temp.transform(p3d);
		Point2d p2d = new Point2d();
		Point canvasLocation = canvas.getLocationOnScreen();
		c.getPixelLocationFromImagePlate(p3d, p2d);
		p2d.x += canvasLocation.x;
		p2d.y += canvasLocation.y;
		Dimension d = c.getSize();
		Dimension sd = Toolkit.getDefaultToolkit().getScreenSize();
		p2d.x = (d.getWidth() / sd.getWidth()) * p2d.x;
		p2d.y = ((d.getHeight() / sd.getHeight()) * (sd.getHeight() - p2d.y));// invert
		return p2d;
	}

	private BranchGroup createSceneGraph()
	/*
	 * The scene graph: sceneBG ---> lights | ---> bg | -----> tg1 ---> model1
	 * -----> tg2 ---> model2 | ---> behavior (controls the bg and the tg's of
	 * the models)
	 */
	{
		BranchGroup sceneBG = new BranchGroup();
		sceneBG.setCapability(BranchGroup.ALLOW_DETACH);
		lightScene(sceneBG); // add lights

		Background bg = makeBackground();
		sceneBG.addChild(bg); // add background

		DetectMarkers detectMarkers = new DetectMarkers(null);

		// the "hiro" marker uses a robot model, scaled by 0.15 units, with no
		// coords file
		String model;
		// model = "robot.3ds";
		model = "05.obj";
		mm1 = new CustomMarkerModel("patt.hiro", model, 0.30, true);
		if (mm1.getMarkerInfo() != null) { // creation was successful
			sceneBG.addChild(mm1.getMoveTg());
			detectMarkers.addMarker(mm1);
		}
		// markerVector.addElement(loadMarkerImage("05"));

		// the "kanji" marker uses a cow model, scaled by 0.12 units, with
		// coords file
		mm2 = new CustomMarkerModel("patt.kanji", "108.obj", 0.30, true);
		if (mm2.getMarkerInfo() != null) {
			sceneBG.addChild(mm2.getMoveTg());
			detectMarkers.addMarker(mm2);
		}
		// markerVector.addElement(loadMarkerImage("108"));
		// setExistedMarker();
		// create a NyAR multiple marker behaviour
		sceneBG.addChild(new NyARMarkersBehavior(cameraParams, bg,
				detectMarkers));
		logger.debug("created NyARMarkersBehavior");

		sceneBG.compile(); // optimize the sceneBG graph

		selected = mm1;
		return sceneBG;
	} // end of createSceneGraph()

	private void lightScene(BranchGroup sceneBG)
	/* One ambient light, 2 directional lights */
	{
		Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
		BoundingSphere bounds = new BoundingSphere(new Point3d(0, 0, 0),
				BOUNDSIZE);

		// Set up the ambient light
		AmbientLight ambientLightNode = new AmbientLight(white);
		ambientLightNode.setInfluencingBounds(bounds);
		sceneBG.addChild(ambientLightNode);

		// Set up the directional lights
		Vector3f light1Direction = new Vector3f(-1.0f, -1.0f, -1.0f);
		// left, down, backwards
		Vector3f light2Direction = new Vector3f(1.0f, -1.0f, 1.0f);
		// right, down, forwards

		DirectionalLight light1 = new DirectionalLight(white, light1Direction);
		light1.setInfluencingBounds(bounds);
		sceneBG.addChild(light1);

		DirectionalLight light2 = new DirectionalLight(white, light2Direction);
		light2.setInfluencingBounds(bounds);
		sceneBG.addChild(light2);
	} // end of lightScene()

	private Background makeBackground()
	// the background will be the current image captured by the camera
	{
		Background bg = new Background();
		BoundingSphere bounds = new BoundingSphere();
		bounds.setRadius(10.0);

		bg.setApplicationBounds(bounds);
		bg.setImageScaleMode(Background.SCALE_FIT_ALL);
		bg.setCapability(Background.ALLOW_IMAGE_WRITE); // so can change image

		return bg;
	} // end of makeBackground()

	private BranchGroup createView(Canvas3D c3d)
	// create a view graph using the camera parameters
	{
		View view = new View();
		ViewPlatform viewPlatform = new ViewPlatform();
		view.attachViewPlatform(viewPlatform);
		view.addCanvas3D(c3d);

		view.setPhysicalBody(new PhysicalBody());
		view.setPhysicalEnvironment(new PhysicalEnvironment());

		view.setCompatibilityModeEnable(true);
		view.setProjectionPolicy(View.PERSPECTIVE_PROJECTION);
		view.setLeftProjection(cameraParams.getCameraTransform()); // camera
																	// projection

		TransformGroup viewGroup = new TransformGroup();
		Transform3D viewTransform = new Transform3D();
		viewTransform.rotY(Math.PI); // rotate 180 degrees
		viewTransform.setTranslation(new Vector3d(0.0, 0.0, 0.0)); // start at
																	// origin
		viewGroup.setTransform(viewTransform);
		viewGroup.addChild(viewPlatform);

		BranchGroup viewBG = new BranchGroup();
		viewBG.addChild(viewGroup);

		return viewBG;
	} // end of createView()

	public void setStatus(String msg)
	// called from DetectMarkers
	{
		// statusTA.setText(msg);
	} // end of setStatus()

	// ------------------------------------------------------------

	public static void main(String args[]) {
		new ProjectGUI();
	}
} // end of MultiNyAR class

